module dogre.configfile;

import std.string;
import std.conv;
import dogre.internals.iteration;
import dogre.internals.utils;

extern(C)
{
    void *getConfigFile();
    void call_ConfigFile_load(void* ptr, const(char)* filename, const(char)* seperators, bool trimWhitespace);
    void *call_getSectionIterator(void* ptr);
    bool call_SectionIterator_hasMoreElements(void* ptr);
    const(char)* call_SectionIterator_peekNextKey(void* ptr);
    void* call_getNext(void* ptr);
    
	struct mm{
            const(char)* first; 
            const(char)* second;
            }
	
    void iter_ConfigFile_SettingsMultiMap(void* ptr, void function(mm, mm[]*), mm[]* container);
}

class ConfigFile
{
    mixin(Wrapper);
    this()
    {
        p = getConfigFile();
    }
	~this(){ }
    void load(string filename, string separators="\t:=", bool trimWhitespace=true)
    {
        call_ConfigFile_load(p, toStringz(filename), toStringz(separators), trimWhitespace);
    }
    ConfigFile.SectionIterator getSectionIterator()
    {
        return new ConfigFile.SectionIterator(call_getSectionIterator(p));
    }



    class SectionIterator
    {
        void* psi;
        this(void* ptr)
        {
            psi = ptr;
        }
        ~this(){ }
        bool hasMoreElements()
        {
            return call_SectionIterator_hasMoreElements(psi);
        }
        
        string peekNextKey()
        {
            return to!string(call_SectionIterator_peekNextKey(psi));
        }
        
        SettingsMultiMap getNext()
        {
            return new SettingsMultiMap(call_getNext(psi));
        }
    }
    
    
    
    class SettingsMultiMap
    {
        void* psmm;
        this(void* ptr)
        {
            psmm = ptr;
        }
        
        int opApply(int delegate(ref string, ref string) dg)
        {
			int result = 0;
			mm[] container;
            iter_ConfigFile_SettingsMultiMap(psmm, &accumulater!mm, &container);
			
            foreach(mm item; container)
            {
				string first = to!string(item.first);
				string second = to!string(item.second);
				result = dg(first, second);
                if(result)
				{
                    break;	
				}
            }
            return result;
        }
    }
}
